home *** CD-ROM | disk | FTP | other *** search
/ Gigarom 1 / Gigarom Macintosh Archives (Quantum Leap)(CDRM1080320)(1993).iso / FILES / HYP / C-D / DartmouthXCMDs.cpt / Dartmouth XCMDs Vol 1&2 / card_2454.txt < prev    next >
Text File  |  1989-02-26  |  22KB  |  612 lines

  1. -- card: 2454 from stack: in
  2. -- bmap block id: 0
  3. -- flags: 0000
  4. -- background id: 3241
  5. -- name: 
  6.  
  7.  
  8. -- part 3 (button)
  9. -- low flags: 00
  10. -- high flags: A003
  11. -- rect: left=64 top=300 right=322 bottom=202
  12. -- title width / last selected line: 0
  13. -- icon id / first selected line: 0 / 0
  14. -- text alignment: 1
  15. -- font id: 0
  16. -- text size: 12
  17. -- style flags: 0
  18. -- line height: 16
  19. -- part name: DeleteResFork
  20. ----- HyperTalk script -----
  21. on mouseUp
  22.   -- This button uses the DeleteResFork XCMD to delete the
  23.   -- resource fork of a stack.
  24.   deleteresfork
  25.   put the result
  26. end mouseUp
  27.  
  28.  
  29.  
  30. -- part 4 (field)
  31. -- low flags: 80
  32. -- high flags: 2007
  33. -- rect: left=12 top=26 right=298 bottom=491
  34. -- title width / last selected line: 0
  35. -- icon id / first selected line: 0 / 0
  36. -- text alignment: 0
  37. -- font id: 22
  38. -- text size: 10
  39. -- style flags: 0
  40. -- line height: 13
  41. -- part name: Source
  42.  
  43.  
  44. -- part 5 (button)
  45. -- low flags: 00
  46. -- high flags: A003
  47. -- rect: left=314 top=300 right=322 bottom=435
  48. -- title width / last selected line: 0
  49. -- icon id / first selected line: 0 / 0
  50. -- text alignment: 1
  51. -- font id: 0
  52. -- text size: 12
  53. -- style flags: 0
  54. -- line height: 16
  55. -- part name: Show LSP Source
  56. ----- HyperTalk script -----
  57. on mouseUp
  58.   set the visible of card field 1 to not the visible of card field 1
  59.   if the visible of card field 1 is true then
  60.     set the name of me to "Hide LSP Source"
  61.   else set the name of me to "Show LSP Source"
  62. end mouseUp
  63.  
  64.  
  65.  
  66. -- part contents for background part 16
  67. ----- text -----
  68. DELETERESFORK XCMD version 1.0
  69. July 7, 1988
  70. Kevin Calhoun
  71.  
  72. DeleteResFork deletes the resource fork of a stack while leaving the data fork intact.
  73.  
  74. Each Macintosh file, including HyperCard stacks, has two forks--a resource fork and a data fork, either of which may be empty.  HyperCard stores all the information about buttons, fields, text, and pictures in the data fork of your stacks.  XCMD's, XFCN's, PICT's, and other resources are stored in the resource fork.
  75.  
  76. DeleteResFork is for that trying moment when you discover that the resource fork of a stack has been ruined.  If this should occur, all of the data HyperCard relies on will still be intact--it's stored in the data fork--but you'll need to jettison your garbled resource fork and then recopy the necessary resources.
  77.  
  78. How can you tell if the resource fork has been ruined?  If ResEdit tells you that there was an error while opening the stack or if a disk utility tells you that the resource fork still takes up disk space even though HyperCard can't find the resources, then you know that your resource fork has been compromised.  (Sometimes HyperCard can't find newly copied resources until you close the stack and then reopen it.  Don't panic until after you've tried this.)
  79.  
  80. DeleteResFork won't let you regain access to a ruined resource fork.  Instead, it just gets rid of it.  It lets you "shake loose" a worthless resource fork that can't be read and start afresh.
  81.  
  82. NOTE:  It's unwise to delete the resource fork of a stack that is already open.  Make a copy of the stack and then work on the copy.
  83.  
  84. INVOKING DELETERESFORK
  85.  
  86. DeleteResFork ¬´fileName¬ª
  87.  
  88. DeleteResFork takes one optional parameter, the full pathname of the file whose resource fork you want to delete.  If the file name is not supplied, a standard file dialog box appears, from which you can select a stack.
  89.  
  90. If the file name supplied is not the full pathname of an extant stack, or if there is any other error, DeleteResFork will return an error message as the Result.  The first word of this message will be "Error."
  91.  
  92. NOTE FOR ADVANCED PROGRAMMERS:
  93. Because XCMD's have no "owned resources" and because there's no official "XCMD Mover," you can never count on resources such as DITL's or STR#'s being around when you need them.  The PrintField XCMD checks for the presence of the proper resources for its dialog.  If they're there it displays its dialog; otherwise it goes ahead and prints without the dialog.  With DeleteResFork, I took a different approach--it creates a dialog without using a DITL resource for the dialog item list.
  94.  
  95. The functions AddButton, AddUserItem, and AddStatText append a new item to a dialog item list in memory.  The function MakeDITL uses these to build an item list from scratch.
  96. (Roger tells me that Tech Note #95, How To Add Items to the Print Dialogs, includes some code that handles the general case of adding an item to an item list.)
  97.  
  98. The drawback to creating a dialog item list on the fly without resources is that you can't alter the text of the dialog (other than the paramText) without recompiling the source code.  However, in the case of XCMD's it may be more valuable to be certain that a vital resource isn't missing than it is to enable alteration of titles and text without source code.
  99.  
  100. Perhaps the ideal solution is to include both the resources and the code to create them on the fly.  If the resources are present, go ahead.  If not, create them.
  101.  
  102. DeleteResFork also contains a filter for ModalDialog that handles the usual keyboard equivalents for Cancel (command-period, command-q, command-Q, escape, tilde) and OK (return and enter).
  103.  
  104. -- part contents for card part 4
  105. ----- text -----
  106. UNIT DeleteResFork;
  107. { DeleteResFork XCMD ¬©1988 by the Trustees of Dartmouth College. }
  108. { Written by John K. Calhoun, Courseware Development. }
  109.  
  110. INTERFACE
  111.   USES
  112.     XCMDIntf;
  113.   TYPE
  114.     Str31 = STRING[31];
  115.  
  116. { type declarations for creating dialog items }
  117.     dItemPtr = ^dialogItem;
  118.     dItemHndl = ^dItemPtr;
  119.     dialogItem = RECORD
  120.         placeholder : handle;
  121.         displayRect : Rect;
  122.         typeAndDataLength : INTEGER;
  123.       END;
  124.  
  125.   PROCEDURE main (paramPtr : XCMDPtr);
  126.  
  127. IMPLEMENTATION
  128.  
  129. {-----------------------------------------------------------------}
  130.  
  131. { The following routines are from the file XCMDUtilities.p. }
  132. { Instead of including the entire XCMD utilities file, }
  133. { we add to our code only the ones we actually need. }
  134. { This trims the size of our XCMD. }
  135.  
  136.   PROCEDURE DoJsr (addr : ProcPtr);
  137.   INLINE
  138.     $205F, $4E90;
  139.  
  140.   FUNCTION EvalExpr (paramPtr : XCmdPtr;
  141.                   expr : Str255) : Handle;
  142.   BEGIN
  143.     WITH paramPtr^ DO
  144.       BEGIN
  145.         inArgs[1] := ORD(@expr);
  146.         request := xreqEvalExpr;
  147.         DoJsr(entryPoint);
  148.         EvalExpr := Handle(outArgs[1]);
  149.       END;
  150.   END;
  151.  
  152.   PROCEDURE ZeroToPas (paramPtr : XCmdPtr;
  153.                   zeroStr : Ptr;
  154.                   VAR pasStr : Str255);
  155.   BEGIN
  156.     WITH paramPtr^ DO
  157.       BEGIN
  158.         inArgs[1] := ORD(zeroStr);
  159.         inArgs[2] := ORD(@pasStr);
  160.         request := xreqZeroToPas;
  161.         DoJsr(entryPoint);
  162.       END;
  163.   END;
  164.  
  165.   FUNCTION StrToNum (paramPtr : XCmdPtr;
  166.                   str : Str31) : LongInt;
  167.   BEGIN
  168.     WITH paramPtr^ DO
  169.       BEGIN
  170.         inArgs[1] := ORD(@str);
  171.         request := xreqStrToNum;
  172.         DoJsr(entryPoint);
  173.         StrToNum := outArgs[1];
  174.       END;
  175.   END;
  176.  
  177.   FUNCTION NumToStr (paramPtr : XCmdPtr;
  178.                   num : LongInt) : Str31;
  179.     VAR
  180.       str : Str31;
  181.   BEGIN
  182.     WITH paramPtr^ DO
  183.       BEGIN
  184.         inArgs[1] := num;
  185.         inArgs[2] := ORD(@str);
  186.         request := xreqNumToStr;
  187.         DoJsr(entryPoint);
  188.         NumToStr := str;
  189.       END;
  190.   END;
  191.  
  192.   FUNCTION PasToZero (paramPtr : XCmdPtr;
  193.                   str : Str255) : Handle;
  194.   BEGIN
  195.     WITH paramPtr^ DO
  196.       BEGIN
  197.         inArgs[1] := ORD(@str);
  198.         request := xreqPasToZero;
  199.         DoJsr(entryPoint);
  200.         PasToZero := Handle(outArgs[1]);
  201.       END;
  202.   END;
  203.  
  204. {-----------------------------------------------------------------}
  205.  
  206.   PROCEDURE GetEventMask (VAR theMask : INTEGER);
  207. { returns the current event mask in theMask }
  208.     CONST
  209.       SysEvtMask = $144;
  210.     TYPE
  211.       IntegerPtr = ^INTEGER;
  212.     VAR
  213.       myIntPtr : IntegerPtr;
  214.   BEGIN
  215.     myIntPtr := IntegerPtr(SysEvtMask);
  216.     theMask := myIntPtr^;
  217.   END;
  218.  
  219.   PROCEDURE PassReturnValue (paramPtr : XCMDPtr;
  220.                   theMsg : Str255); { set theResult }
  221.   BEGIN
  222.     paramPtr^.returnValue := PasToZero(paramPtr, theMsg);
  223.   END;
  224.  
  225.   FUNCTION GetLocOfCardWindow (paramPtr : XCmdPtr) : point;
  226. { returns the top left corner of the card window }
  227.     VAR
  228.       theResult : Handle;
  229.       aString : Str255;
  230.       theLoc : point;
  231.   BEGIN
  232.     theResult := EvalExpr(paramPtr, 'item 1 of the loc of card window');
  233.     ZeroToPas(paramPtr, theResult^, aString);
  234.     DisposHandle(theResult);
  235.     theLoc.h := StrToNum(paramPtr, aString);
  236.  
  237.     theResult := EvalExpr(paramPtr, 'item 2 of the loc of card window');
  238.     ZeroToPas(paramPtr, theResult^, aString);
  239.     DisposHandle(theResult);
  240.     theLoc.v := StrToNum(paramPtr, aString);
  241.     GetLocOfCardWindow := theLoc;
  242.   END;
  243.  
  244.   FUNCTION MyFilter (theDialog : DialogPtr;
  245.                   VAR theEvent : EventRecord;
  246.                   VAR itemHit : INTEGER) : BOOLEAN;
  247. { filter function for modal dialog -- handles the usual key equivalents for OK and Cancel }
  248.     VAR
  249.       theChar : char;
  250.       dummy : EventRecord;
  251.  
  252.     PROCEDURE PushButton (itemNo : INTEGER);
  253. { Hilites the button itemNo while a key is pressed. }
  254. { For this to work properly, the event mask must be set to allow }
  255. { keyUp events to be detected -- that's why the call to ModalDialog, }
  256. { below, is bracketed by calls to SetEventMask. }
  257.       VAR
  258.         itemType : INTEGER;
  259.         itemHandle : Handle;
  260.         itemBox : Rect;
  261.     BEGIN  { procedure PushButton }
  262.       GetDItem(theDialog, itemNo, itemType, itemHandle, itemBox);
  263.       HiliteControl(ControlHandle(itemHandle), inButton);
  264.       REPEAT
  265.       UNTIL OSEventAvail(keyUpMask, dummy);
  266.       HiliteControl(ControlHandle(itemHandle), 0);
  267.     END;
  268.  
  269.   BEGIN  { function MyFilter }
  270.     MyFilter := FALSE;
  271.     CASE theEvent.what OF
  272.       keyDown, autoKey : 
  273.         BEGIN
  274.           theChar := CHR(BitAnd(theEvent.message, charCodeMask));
  275.           IF BitAnd(theEvent.modifiers, cmdKey) <> 0 THEN
  276.             BEGIN
  277.               MyFilter := TRUE;
  278.               CASE ORD(theChar) OF
  279.                 46, 81, 113 :
  280. { if user pressed command-period, -q, or -Q, then do Cancel }
  281.                   BEGIN
  282.                     PushButton(Cancel);
  283.                     itemHit := Cancel;
  284.                     MyFilter := TRUE;
  285.                   END;
  286.               END;
  287.             END
  288.           ELSE
  289.             CASE ORD(theChar) OF
  290.               13, 3 :
  291. { if the user pressed return or enter, do OK }
  292.                 BEGIN
  293.                   PushButton(OK);
  294.                   itemHit := OK;
  295.                   MyFilter := TRUE;
  296.                 END;
  297.               27, 96 :
  298. { if user pressed the escape key or the tilde key, do Cancel }
  299.                 BEGIN
  300.                   PushButton(Cancel);
  301.                   itemHit := Cancel;
  302.                   MyFilter := TRUE;
  303.                 END;
  304.             END;
  305.         END;
  306.     END;
  307.   END;
  308.  
  309.   PROCEDURE DrawBoxAroundDefault (theWindow : WindowPtr;
  310.                   itemNo : INTEGER);
  311. { draws the bold rounded-corner rect around the default button }
  312.     VAR
  313.       itemType : integer;
  314.       itemHdl : Handle;
  315.       itemBox : rect;
  316.   BEGIN
  317.     GetDItem(theWindow, 1, itemType, itemHdl, itemBox);
  318.     PenSize(3, 3);
  319.     InsetRect(itemBox, -4, -4);
  320.     FrameRoundRect(itemBox, 16, 16);
  321.     PenSize(1, 1);
  322.   END;
  323.  
  324.   PROCEDURE DrawVersionInfo (theWindow : WindowPtr;
  325.                   itemNo : INTEGER);
  326. { draws the version info for the XCMD in the dialog box }
  327.     VAR
  328.       itemType : integer;
  329.       itemHdl : Handle;
  330.       itemBox : rect;
  331.       str : Str255;
  332.   BEGIN
  333.     str := 'DeleteResFork XCMD 1.0   ¬©1988 Dartmouth College';
  334.     GetDItem(theWindow, itemNo, itemType, itemHdl, itemBox);
  335.     TextFont(Geneva);
  336.     TextSize(9);
  337.     TextBox(POINTER(ORD(@str) + 1), LENGTH(str), itemBox, teJustLeft);
  338.     TextFont(SystemFont);
  339.     TextSize(12);
  340.   END;
  341.  
  342.   FUNCTION AddButton (boundsRect : rect;
  343.                   title : Str255;
  344.                   VAR theItems : Handle) : OSErr;
  345. { add information for a new button item to the end of the DITL theItems }
  346.     VAR
  347.       newItem : DItemHndl;
  348.       err : OSErr;
  349.   BEGIN
  350.     newItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  351.     err := MemError;
  352.     IF (newItem <> NIL) AND (err = noErr) THEN
  353.       BEGIN
  354.         MoveHHi(Handle(newItem));
  355.         HLock(Handle(newItem));
  356.         WITH newItem^^ DO
  357.           BEGIN
  358.             placeholder := NIL;
  359.             displayRect := boundsRect;  { item rectangle }
  360.             typeAndDataLength := (ctrlItem + btnCtrl) * 256 + LENGTH(title);
  361.              { high byte contains itemType, low byte contains length of 
  362.                    the button title }
  363.           END;
  364.         err := HandAndHand(Handle(newItem), theItems);  { copy this info into item list }
  365.         IF err = noErr THEN
  366.           err := PtrAndHand(POINTER(ORD4(@title) + 1), theItems, LENGTH(title));
  367.                { copy the title into the item list }
  368.         HUnlock(Handle(newItem));
  369.         DisposHandle(Handle(newItem));
  370.       END;
  371.     AddButton := err;
  372.   END;
  373.  
  374.   FUNCTION AddUserItem (boundsRect : rect;
  375.                   theProc : ProcPtr;
  376.                   VAR theItems : Handle) : OSErr;
  377. { add information for a new user item to the end of the DITL theItems }
  378.     VAR
  379.       theUserItem : DItemHndl;
  380.       err : OSErr;
  381.   BEGIN
  382.     theUserItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  383.     err := MemError;
  384.     IF (theUserItem <> NIL) AND (err = noErr) THEN
  385.       BEGIN
  386.         MoveHHi(Handle(theUserItem));
  387.         HLock(Handle(theUserItem));
  388.         WITH theUserItem^^ DO
  389.           BEGIN
  390.             placeholder := Handle(theProc);
  391.             displayRect := boundsRect;  { item rectangle }
  392.             typeAndDataLength := userItem * 256 + 0;
  393.              { high byte contains itemType, low byte contains nothing } 
  394.           END;
  395.         err := HandAndHand(Handle(theUserItem), theItems);
  396.           { copy this info into the item list }
  397.         HUnlock(Handle(theUserItem));
  398.         DisposHandle(Handle(theUserItem));
  399.       END;
  400.     AddUserItem := err;
  401.   END;
  402.  
  403.   FUNCTION AddStatText (boundsRect : rect;
  404.                   str : Str255;
  405.                   VAR theItems : Handle) : OSErr;
  406. { add information for a new statText item to the end of the DITL theItems }
  407.     VAR
  408.       theStatTextItem : DItemHndl;
  409.       err : OSErr;
  410.   BEGIN
  411.     theStatTextItem := DItemHndl(NewHandle(SIZEOF(DialogItem)));
  412.     err := MemError;
  413.     IF (theStatTextItem <> NIL) AND (err = noErr) THEN
  414.       BEGIN
  415.         MoveHHi(Handle(theStatTextItem));
  416.         HLock(Handle(theStatTextItem));
  417.         WITH theStatTextItem^^ DO
  418.           BEGIN
  419.             placeholder := NIL;
  420.             displayRect := boundsRect;  { item rectangle }
  421.             typeAndDataLength := (statText + itemDisable) * 256 + LENGTH(str);
  422.              { high byte contains itemType, low byte contains length of 
  423.                    the text to be displayed }
  424.           END;
  425.         err := HandAndHand(Handle(theStatTextItem), theItems);
  426.           { copy this info into the item list }
  427.         IF err = noErr THEN
  428.           err := PtrAndHand(POINTER(ORD4(@str) + 1), theItems, LENGTH(str));
  429.                { copy the text into the item list }
  430.         HUnlock(Handle(theStatTextItem));
  431.         DisposHandle(Handle(theStatTextItem));
  432.       END;
  433.     AddStatText := err;
  434.   END;
  435.  
  436.   FUNCTION MakeDITL (VAR theItems : Handle) : OSErr;
  437. { Create our dialog item list on the fly. }
  438. { We rely heavily on the information given in IM-I, p. 427 }
  439.     CONST
  440.       numItems = 6;
  441.     VAR
  442.       myStatTextItem : dItemHndl;
  443.       err : OSErr;
  444.       itemCount : INTEGER;
  445.       str : Str255;
  446.       theRect : Rect;
  447.   BEGIN
  448.     theItems := NewHandle(2);
  449. { We'll build this handle into a full item list by appending info to it }
  450. { using BlockMove, HandAndHand, and PtrAndHand. }
  451.     IF theItems <> NIL THEN
  452.       BEGIN
  453.         itemCount := numItems - 1;
  454.         BlockMove(@itemCount, theItems^, 2);
  455.          { first two bytes of the DITL = number of items in list minus 1 }
  456.         SetRect(theRect, 230, 100, 300, 120);
  457.         err := AddButton(theRect, 'OK', theItems);
  458.           { add the OK button to the item list }
  459.         IF err = noErr THEN
  460.           BEGIN
  461.             SetRect(theRect, 140, 100, 210, 120);
  462.               { add the Cancel button to the item list }
  463.             err := AddButton(theRect, 'Cancel', theItems);
  464.             IF err = noErr THEN
  465.               BEGIN
  466.                 SetRect(theRect, 220, 90, 310, 130);
  467.                 err := AddUserItem(theRect, @DrawBoxAroundDefault, theItems);
  468.                   { add the default button user item to the item list }
  469.                 IF err = noErr THEN
  470.                   BEGIN
  471.                     SetRect(theRect, 10, 97, 130, 125);
  472.                     err := AddUserItem(theRect, @DrawVersionInfo, theItems);
  473.                       { add the version info user item to the item list }
  474.                     IF err = noErr THEN
  475.                       BEGIN
  476.                         SetRect(theRect, 10, 10, 302, 50);
  477.                         str := 'Are you sure you want to delete the resource fork of: ';
  478.                         err := AddStatText(theRect, str, theItems);
  479.                           { put this string in a stat text item and }
  480.                           { add it to the item list }
  481.                         IF err = noErr THEN
  482.                           BEGIN
  483.                             SetRect(theRect, 10, 52, 302, 92);
  484.                             str := '‚Äú^0‚Äù? ';
  485.                             err := AddStatText(theRect, str, theItems);
  486.                               { put this string in a stat text item and }
  487.                               { add it to the item list }
  488.                           END;  { if err = noErr when creating the first statText item }
  489.                       END;  { if err = noErr when creating the version info userItem }
  490.                   END;  { if err = noErr when creating the default button userItem }
  491.               END;  { if err = noErr when creating Cancel Button }
  492.           END;  { if err = noErr when creating OK button }
  493.       END; { if theItems <> nil }
  494.     MakeDITL := err;
  495.   END;
  496.  
  497.   PROCEDURE DoSFGet (cardLoc : Point;
  498.                   VAR SFGetReply : SFReply);
  499.     VAR
  500.       where : point;
  501.       typeList : SFTypeList;
  502.   BEGIN  { select text file to read using SFGetFile }
  503. { in order to align the dialog box over the current location of the card window }
  504.     SetPt(where, 82, 75); { tell SFGetFile where to put the dialog box }
  505.     AddPt(cardLoc, where);  { align the dialog box with current location }
  506.                                  { of the card window }
  507.     typeList[0] := 'STAK'; { tell SFGetFile to display only text files }
  508.     SFGetFile(where, '', NIL, 1, typeList, NIL, SFGetReply);          
  509.         { call SFGetFile }
  510.   END;
  511.  
  512.   FUNCTION DeleteResourceFork (fName : Str255;
  513.                   vRefNum : INTEGER) : OSErr;
  514. { delete the resource fork of a file }
  515.     VAR
  516.       theRefNum : INTEGER;
  517.       closeErr, err : OSErr;
  518.   BEGIN
  519.     err := OpenRF(fName, vRefNum, theRefNum);  { open the file }
  520.  
  521.     IF err = noErr THEN { continue only if file could be opened }
  522.       BEGIN
  523.         err := SetEOF(theRefNum, 0);  { set the length of the resource fork to 0 }
  524.         closeErr := FSClose(theRefNum);  { close the file }
  525.       END;
  526.     DeleteResourceFork := err;
  527.   END; { procedure DeleteResourceFork }
  528.  
  529.   PROCEDURE SaveTheData (paramPtr : XCMDPtr);
  530.     VAR
  531.       cardLoc : point;
  532.       SFGetReply : SFReply;
  533.       err : OSErr;
  534.       gotAFile : BOOLEAN;
  535.       theFileName : Str255;
  536.       theVRefNum : INTEGER;
  537.       fndrInfo : FInfo;
  538.       myItems : Handle;
  539.       bounds : rect;
  540.       myDialog : DialogPtr;
  541.       theMask : INTEGER;
  542.       itemHit : INTEGER;
  543.  
  544.   BEGIN { procedure SaveTheData }
  545.     cardLoc := GetLocOfCardWindow(paramPtr);
  546.     gotAFile := FALSE;
  547.     IF paramPtr^.paramCount < 1 THEN
  548. { user did not specify a file -- put up standard file dialog box }
  549.       BEGIN
  550.         DoSFGet(cardLoc, SFGetReply);
  551.         IF SFGetReply.good = TRUE THEN
  552.           BEGIN         { continue only if user actually selected a file }
  553.             WITH SFGetReply DO
  554.               BEGIN
  555.                 theFileName := fName;
  556.                 theVRefNum := vRefNum;
  557.               END;  { with SFGetReply }
  558.             gotAFile := TRUE;
  559.           END;
  560.       END
  561.     ELSE
  562. { user specified a file -- check to see if it's really a stack }
  563.       BEGIN
  564.         ZeroToPas(paramPtr, paramPtr^.params[1]^, theFileName);
  565.         err := GetFInfo(theFileName, 0, fndrInfo);
  566.         IF (err = noErr) AND (fndrInfo.fdType = 'STAK') THEN
  567.           BEGIN
  568.             gotAFile := TRUE;
  569.             theVRefNum := 0;
  570.           END
  571.         ELSE IF err <> noErr THEN
  572.           PassReturnValue(paramPtr, CONCAT('Error ', NumToStr(paramPtr, err)))
  573.         ELSE
  574.           PassReturnValue(paramPtr, 'Error -- that file is not a stack');
  575.       END;
  576.     IF gotAFile THEN
  577.       BEGIN
  578. { create our dialog item list on the fly and put up our dialog }
  579.         err := MakeDITL(myItems);
  580.         IF err = noErr THEN
  581.           BEGIN
  582. { calculate boundsRect of dialog and display it }
  583.             WITH cardLoc DO
  584.               SetRect(bounds, h + 100, v + 80, h + 412, v + 210);
  585.             ParamText(theFileName, '', '', '');
  586.             myDialog := NewDialog(NIL, bounds, '', TRUE, dBoxProc, POINTER(-1), FALSE, 0, myItems);
  587.             GetEventMask(theMask);
  588.             SetEventMask(everyEvent);
  589. { Our filter proc for ModalDialog needs keyUp events, }
  590. { so we set the event mask so that it gets them }
  591. { and then restore the event mask after the dialog is removed. }
  592.             REPEAT
  593.               ModalDialog(@MyFilter, itemHit);
  594.             UNTIL (itemHit = OK) OR (itemHit = Cancel);
  595.             SetEventMask(theMask);
  596.             DisposDialog(myDialog);
  597.             DisposHandle(myItems);
  598.             IF itemHit = OK THEN
  599. { user gave the go-ahead, so go ahead and delete the resource fork }
  600.               err := DeleteResourceFork(theFileName, theVRefNum);
  601.           END;
  602.         IF err <> noErr THEN  { return error message }
  603.           PassReturnValue(paramPtr, CONCAT('Error ', NumToStr(paramPtr, err)));
  604.       END; { if gotAFile }
  605.   END;  { of procedure SaveThatData }
  606.  
  607.   PROCEDURE main;
  608.   BEGIN
  609.     SaveTheData(paramPtr);
  610.   END;
  611.  
  612. END.